import Taro from '@tarojs/taro'
import { EE, UN_LOGIN } from './emitter'

// 请求配置
const config = {
  timeout: 60000,
  responseType: 'json'
}

// 响应拦截器
const responseInterceptor = (response, options) => {
  const { statusCode, data } = response
  
  // HTTP状态码检查
  if (statusCode >= 200 && statusCode < 300) {
    // 业务状态码检查 - 支持配置化
    const successCode = process.env.TARO_APP_SUCCESS_CODES || '0'
    const isSuccess = successCode === String(data.code)
    
    if (isSuccess) {
      return data
    } else {
      // 业务错误处理
      const errorMsg = data.message || data.msg || '请求失败'
      throw new Error(errorMsg)
    }
  } else {
    // HTTP错误处理映射表
    const errorMap = {
      401: '未授权，请重新登录',
      403: '拒绝访问',
      404: '请求地址不存在',
      500: '服务器内部错误'
    }
    
    const errorMsg = errorMap[statusCode] || `网络错误 ${statusCode}`
    
    // 401状态特殊处理 - 使用emitter解耦
    if (statusCode === 401) {
      Taro.removeStorageSync('token')
      EE.emit(UN_LOGIN, { statusCode, errorMsg })
    }
    
    throw new Error(errorMsg)
  }
}

// 错误处理
const errorHandler = (error, options) => {
  let errorMsg = '网络连接失败'
  if (error.errMsg) {
    if (error.errMsg.includes('timeout')) {
      errorMsg = '请求超时'
    } else if (error.errMsg.includes('fail')) {
      errorMsg = '网络连接失败'
    }
  }
  
  throw error
}

/**
 * 构建请求URL（GET/DELETE方法将参数拼接到URL）
 */
const buildRequestUrl = (url, method, data) => {
  if (!(['GET', 'DELETE'].includes(method)) || !data || !Object.keys(data).length) {
    return url
  }
  const params = new URLSearchParams(data).toString()
  return `${url}${url.indexOf('?') === -1 ? '?' : '&'}${params}`
}

/**
 * 构建请求头
 */
const buildHeaders = (options) => {
  const token = Taro.getStorageSync('token')
  return {
    'Content-Type': options.contentType || 'application/json',
    ...(token && { 'Authorization': `Bearer ${token}` }),
    ...options.header
  }
}

/**
 * 处理请求数据
 */
const processRequestData = (method, data, contentType) => {
  if (!['POST', 'PUT', 'PATCH'].includes(method) || !data) {
    return undefined
  }
  
  if (contentType === 'application/x-www-form-urlencoded') {
    return new URLSearchParams(data).toString()
  }
  
  if (contentType === 'multipart/form-data') {
    return data // FormData对象直接使用
  }
  
  return JSON.stringify(data)
}

/**
 * 统一请求方法
 * @param {string} url - 请求URL（相对路径）
 * @param {Object} options - 请求配置选项
 * @param {string} options.method - HTTP方法（GET、POST、PUT、PATCH、DELETE）
 * @param {Object} options.data - 请求数据
 * @param {Object} options.header - 自定义请求头
 * @param {number} options.timeout - 超时时间（毫秒）
 * @param {string} options.contentType - 内容类型
 * @param {string} options.responseType - 响应类型
 * @param {string} options.type - 特殊请求类型（'upload'上传文件、'download'下载文件）
 * 
 * 文件上传专用配置（当type='upload'时）:
 * @param {string} options.filePath - 文件路径
 * @param {string} options.name - 文件字段名（默认'file'）
 * @param {Object} options.formData - 额外的表单数据
 * @param {Function} options.onUploadProgress - 上传进度回调函数
 * 
 * 文件下载专用配置（当type='download'时）:
 * @param {string} options.fileName - 下载文件名（可选，用于自定义文件名）
 * 
 * @returns {Promise<[data, error]>} 返回[数据, 错误]的数组格式
 */
const request = async (url, options = {}) => {
  try {
    const method = (options.method || 'GET').toUpperCase()
    const requestUrl = buildRequestUrl(url, method, options.data)
    const headers = buildHeaders(options)
    const requestData = processRequestData(method, options.data, options.contentType)
    
    let response
    
    // 根据请求类型选择不同的处理方式
    switch (options.type) {
      case 'upload':
        const uploadTask = Taro.uploadFile({
          url: requestUrl,
          filePath: options.filePath,
          name: options.name || 'file',
          header: headers,
          formData: options.formData || {},
          timeout: options.timeout || config.timeout
        })
        
        // 监听上传进度
        if (options.onUploadProgress && typeof options.onUploadProgress === 'function') {
          uploadTask.progress((res) => {
            options.onUploadProgress({
              progress: res.progress,
              totalBytesSent: res.totalBytesSent,
              totalBytesExpectedToSend: res.totalBytesExpectedToSend
            })
          })
        }
        
        response = await uploadTask
        // 处理上传响应
        const uploadData = JSON.parse(response.data)
        const successCode = process.env.TARO_APP_SUCCESS_CODES || '0'
        const isUploadSuccess = successCode === String(uploadData.code)
        if (isUploadSuccess) {
          return [uploadData, null]
        } else {
          const errorMsg = uploadData.message || uploadData.msg || '上传失败'
          throw new Error(errorMsg)
        }
        
      case 'download':
         const downloadOptions = {
           url: requestUrl,
           header: headers,
           timeout: options.timeout || config.timeout
         }
         
         // 如果指定了文件名，则使用自定义文件名
         if (options.fileName) {
           downloadOptions.filePath = options.fileName
         }
         
         response = await Taro.downloadFile(downloadOptions)
        if (response.statusCode === 200) {
          return [response, null]
        } else {
          throw new Error('下载失败')
        }
        
      default:
        const requestOptions = {
          url: requestUrl,
          method,
          header: headers,
          data: requestData,
          timeout: options.timeout || config.timeout,
          responseType: options.responseType || config.responseType
        }
        
        response = await Taro.request(requestOptions)
        const data = await responseInterceptor(response, requestOptions)
        return [data, null]
    }
  } catch (error) {
    errorHandler(error, options)
    return [null, error]
  }
}

// 只导出request方法
export default request

/*
使用示例：

// 1. GET请求
const [users, error] = await request('/api/users', {
  method: 'GET',
  data: { page: 1, size: 10 }
})
if (error) {
  console.error('获取用户列表失败:', error)
} else {
  console.log('用户列表:', users)
}

// 2. POST请求（JSON格式）
const [loginResult, loginError] = await request('/api/login', {
  method: 'POST',
  data: {
    username: 'admin',
    password: '123456'
  }
})

// 3. POST请求（表单格式）
const [formResult, formError] = await request('/api/form', {
  method: 'POST',
  contentType: 'application/x-www-form-urlencoded',
  data: {
    name: 'test',
    email: 'test@example.com'
  }
})

// 4. PUT请求
const [updateResult, updateError] = await request('/api/user/123', {
  method: 'PUT',
  data: {
    name: 'Updated Name',
    email: 'new@example.com'
  }
})

// 5. DELETE请求
const [deleteResult, deleteError] = await request('/api/user/123', {
  method: 'DELETE'
})

// 6. 文件上传（带进度监听）
const [uploadResult, uploadError] = await request('/api/upload', {
  type: 'upload',
  filePath: filePath,
  name: 'avatar',
  formData: {
    userId: 123,
    category: 'profile'
  },
  onUploadProgress: (progress) => {
    console.log(`上传进度: ${progress.progress}%`)
    // 更新UI进度条
    setUploadProgress(progress.progress)
  }
})

// 7. 文件下载（自定义文件名）
const [downloadResult, downloadError] = await request('/api/file/456', {
  type: 'download',
  fileName: 'document.pdf'
})

// 8. 监听401未授权事件（在app.js中）
import { EE, UN_LOGIN } from '@/utils/emitter'

EE.on(UN_LOGIN, ({ statusCode, errorMsg }) => {
  console.log('用户未授权，跳转到登录页')
  Taro.showToast({
    title: errorMsg,
    icon: 'none'
  })
  Taro.navigateTo({ url: '/subPackages/login/index' })
})
*/